﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;

namespace WebApp.Hubs
{
    public class ServiceChatHub : Hub
    {
        // This will only work on a single server
        private static readonly ConcurrentDictionary<string, List<string>> UserConnections = new ConcurrentDictionary<string, List<string>>();

        public void SendAll(string message)
        {
            Clients.All.showMessage(message);
        }

        public void SendPrivate(string message, string who)
        {
            List<string> connections;
            if (UserConnections.TryGetValue(who, out connections))
            {
                // Get a list of connections for the user we want to send a message to
                // Send a message to each user, and tell them who it came from
                Clients.Clients(connections).showMessage(message);
            }
        }

        public override async Task OnConnected()
        {
            // Make a new slot of get a list of connections for this user name
            var connections = UserConnections.GetOrAdd(Context.User.Identity.Name, _ => new List<string>());

            lock (connections)
            {
                // Add the connection to the list of connections. This allows one user to log in from
                // different clients (broser tabs, browsers, mobile devices, other apps, etc),
                // and have them all be synchronized.
                connections.Add(Context.ConnectionId);
            }

            await Task.Delay(100);
        }

        public override async Task OnDisconnected()
        {
            List<string> connections;
            var userName = Context.User.Identity.Name;

            if (UserConnections.TryGetValue(userName, out connections))
            {
                lock (connections)
                {
                    // Remove the connection from the list of connections
                    connections.Remove(Context.ConnectionId);
                }

                // In case this is a browser refresh, wait a few milli seconds before removing all connections
                // This way, hitting f5 don't suddenly cause an offline/online flip
                await Task.Delay(100);

                if (connections.Count == 0)
                {
                    UserConnections.TryRemove(userName, out connections);
                }
            }
        }
    }
}